package com.cai.game;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Random;

/**
 * @author 若离
 * 面板
 */
public class GamePanel extends JPanel implements KeyListener, ActionListener {
    /**
     * 定义蛇的数据结构
     * 蛇的长度 length
     * 蛇的x坐标 snakeX 25*25
     * 蛇的y坐标 snakeY 25*25
     * 食物坐标 foodx foody
     * 头的初始方向 fx
     * 游戏状态 开始|停止 isStart
     * 游戏是否失败
     * 定时器 timer 100ms刷新一次 1000ms=1s
     * 成绩 score
     */
    int length;
    int[] snakeX = new int[600];
    int[] snakeY = new int[500];
    int foodx;
    int foody;
    Random random = new Random();
    String fx;
    boolean isStart;
    boolean isFail;
    Timer timer = new Timer(100, this);
    int score;

    /**
     * 构造器
     */
    public GamePanel() {
        init();
        //获取焦点事件和键盘事件
        this.setFocusable(true);
        this.addKeyListener(this);
        timer.start();
    }

    /**
     * 初始化方法
     */
    public void init() {
        length = 3;
        //脑袋坐标
        snakeX[0] = 100;
        snakeY[0] = 100;
        //第一个身体坐标
        snakeX[1] = 75;
        snakeY[1] = 100;
        //第二个身体坐标
        snakeX[2] = 50;
        snakeY[2] = 100;
        //初始方向 右
        fx = "R";
        //随机食物坐标
        foodx = 25 + 25 * random.nextInt(34);
        foody = 75 + 25 * random.nextInt(24);
        //成绩
        score = 0;
    }

    /**
     * 画笔实现类
     *
     * @param g 画笔
     */
    @Override
    public void paint(Graphics g) {
        //清屏
        super.paintComponent(g);
        this.setBackground(Color.white);
        //绘制静态面板
        //头部广告栏
//        Data.header.paintIcon(this, g, 25, 11);
        //画矩形 默认游戏界面
        g.fillRect(25, 75, 850, 600);
        //判断蛇头方向,加入蛇头
        switch (fx) {
            case "R":
                Data.right.paintIcon(this, g, snakeX[0], snakeY[0]);
                break;
            case "L":
                Data.left.paintIcon(this, g, snakeX[0], snakeY[0]);
                break;
            case "U":
                Data.up.paintIcon(this, g, snakeX[0], snakeY[0]);
                break;
            case "D":
                Data.down.paintIcon(this, g, snakeX[0], snakeY[0]);
                break;
            default:
                break;
        }
        //画身体 根据长度
        for (int i = 1; i < length; i++) {
            Data.body.paintIcon(this, g, snakeX[i], snakeY[i]);
        }
        //画食物
        Data.food.paintIcon(this, g, foodx, foody);
        //游戏状态
        if (!isStart) {
            g.setColor(Color.white);
            g.setFont(new Font("微软雅黑", Font.BOLD, 40));
            g.drawString("按下空格开始游戏", 300, 300);
        }
        //判定是否失败
        if (isFail) {
            g.setColor(Color.red);
            g.setFont(new Font("微软雅黑", Font.BOLD, 40));
            g.drawString("游戏失败,按下空格重新开始", 300, 300);
        }
        //画成绩
        g.setColor(Color.black);
        g.setFont(new Font("微软雅黑", Font.BOLD, 18));
        g.drawString("长度：" + length, 750, 30);
        g.drawString("分数：" + score, 750, 50);
    }

    @Override
    public void keyTyped(KeyEvent e) {

    }

    /**
     * 键盘按压事件
     *
     * @param e 键盘按键
     */
    @Override
    public void keyPressed(KeyEvent e) {
        //获取键盘案件是哪一个
        int keyCode = e.getKeyCode();
        switch (keyCode) {
            //按下空格
            case KeyEvent.VK_SPACE:
                if (isFail) {
                    isFail = false;
                    init();
                } else {
                    //取反
                    isStart = !isStart;
                }
                //重新绘制 状态发生变化
                repaint();
                break;
            case KeyEvent.VK_UP:
                fx = "U";
                break;
            case KeyEvent.VK_DOWN:
                fx = "D";
                break;
            case KeyEvent.VK_LEFT:
                fx = "L";
                break;
            case KeyEvent.VK_RIGHT:
                fx = "R";
                break;
            default:
                break;
        }
    }

    @Override
    public void keyReleased(KeyEvent e) {

    }

    /**
     * 事件监听... 需要通过固定的事件刷新
     */
    @Override
    public void actionPerformed(ActionEvent e) {
        if (isStart && !isFail) {
            //开始状态,让小蛇动起来
            for (int i = length - 1; i > 0; i--) {
                //向前移动一节
                snakeX[i] = snakeX[i - 1];
                snakeY[i] = snakeY[i - 1];
            }
            //走向
            switch (fx) {
                case "R":
                    snakeX[0] = snakeX[0] + 25;
                    //边界判断
                    if (snakeX[0] > 850) {
                        snakeX[0] = 25;
                    }
                    break;
                case "L":
                    snakeX[0] = snakeX[0] - 25;
                    //边界判断
                    if (snakeX[0] < 25) {
                        snakeX[0] = 850;
                    }
                    break;
                case "U":
                    snakeY[0] = snakeY[0] - 25;
                    //边界判断
                    if (snakeY[0] < 75) {
                        snakeY[0] = 650;
                    }
                    break;
                case "D":
                    snakeY[0] = snakeY[0] + 25;
                    //边界判断
                    if (snakeY[0] > 650) {
                        snakeY[0] = 75;
                    }
                    break;
                default:
                    break;
            }
            //吃食物 头和食物重合
            if (snakeX[0] == foodx && snakeY[0] == foody) {
                //小蛇长度增加
                length++;
                //加分数
                score = score + 10;
                //再次随机食物
                //随机食物坐标
                foodx = 25 + 25 * random.nextInt(34);
                foody = 75 + 25 * random.nextInt(24);

            }
            //失败判定，撞到自己就算失败
            for (int i = 1; i < length; i++) {
                if (snakeX[0] == snakeX[i] && snakeY[0] == snakeY[i]) {
                   isFail=true;
                }
            }
            //重新绘制
            repaint();
        }
        timer.start();

    }

}

